#include <iostream>
#include <functional>

using std::cout;
using std::endl;
using std::bind;

int add(int x, int y, int z)
{
    cout << "int add(int, int, int)" << endl;
    return x + y + z;
}

class Test
{
public:
    int add(int x, int y)
    {
        cout << "int Test::add(int, int)" << endl;
        return x + y;
    }
};

void test()
{
    //函数的形态（函数的类型）：函数的返回类型 + 函数的参数列表
    //函数的参数列表：函数的参数的个数、参数的类型、参数的顺序
    //bind可以改变函数的形态(只能改变函数的参数个数)
    auto f = bind(&add, 1, 2, 3);
    cout << "f() = " << f() << endl;

    Test tst;
    auto f2 = bind(&Test::add, &tst, 1, 2);
    cout << "f2() = " << f2() << endl;

    auto f3 = bind(&Test::add, tst, 10, 20);
    cout << "f3() = " << f3() << endl;

    //占位符
    using namespace std::placeholders;
    //add ===>int(int, int, int)
    //f4===>int(int)
    auto f4 = bind(&add, 1, _1, 3);
    cout <<"f4(10) = " << f4(10, 20, 30) << endl;
}

void func(int x1, int x2, int x3, const int &x4, int x5)
{
    cout << "x1 = " << x1 << endl
         << "x2 = " << x2 << endl
         << "x3 = " << x3 << endl
         << "x4 = " << x4 << endl
         << "x5 = " << x5 << endl;
}

void test2()
{
    int number = 30;
    using namespace std::placeholders;
    //占位符本身代表的是形参的位置
    //占位符中的数字代表的是实参的位置
    //bind默认采用的是值传递
    //引用的包装器,std::cref
    //引用的包装器,std::ref
    auto f = bind(&func, 10, _3, _1,std::cref(number), number);
    number = 200;
    f(20, 50, 70, 90, 300, 500, 1000);//其他没有使用的参数直接丢掉
}

int main(int argc, char **argv)
{
    test2();
    return 0;
}

